/* file: cg_image.h */

#ifndef _CG_IMAGE_H
#define _CG_IMAGE_H

#include "gp.h"

struct Position
{
    string ip;
    int level;
};
typedef vector<Position> Set;

/*************************************************
class name: CGImage
*************************************************/
class CGImage
{
protected:
    struct node
    {
    	// string ip;		// IP address of CGNode
    	CGNodeStatus state;	// ONLINE or OFFLINE
    	string father;		// IP address of its father, "0.0.0.0" if root's father
    	int level;		// depth of CGNode in CGTree, 0 if root
    	// int prior;		// priority of CGNode within its siblings
    	vector<string> group;	// IP address of its group member
    };
    /* image of CGTree */
    map<string, vector<node> > tree;	// image of sub_tree
    string ip;				// current node's IP address
    int level;				// current node's level
    string father;			// current node's father
    string root;			// IP address of CGTree's root
    int depth;				// depth of CGImage

    pthread_mutex_t lock;
    
public:
    /* constructor */
    CGImage();
    CGImage(string ip, int level, string root, int depth);
    //virtual ~CGImage();
    
public:
    void setPosition(const string &str, int l) { ip = str; level = l; }
    void setRoot(const string &str) { root = str; }
    void setFather(const string &ip);
    
    string getIP() { return ip; }
    string getFather() { return father; }
    string getRoot() { return root; }
    int getDepth() { return depth; }
    
public:
    int loadCGImage(char *filename);	// load the whole cg_tree from config file
    					// used in the real_node's cgtree
    void initPosition(const string &ip, int level, string root, int depth);	// called by CGNode to initialize a CGImage
    
    void printCGMap();			// print the cg_tree in map<ip, vector<node>> format
    void printCGTree();			// print the cg_tree in sub_tree format
    void printSubTree(string sub_ip, int sub_level, char *str);		// called by CGImage::printCGTree to do recursive procedure

    int codeCGImage(string ip, int level, char *str);
    int codeSubImage(string sub_ip, int sub_level, char *str, int offset);	// called by CGImage::codeCGImage to do recursive procedure
    
    int buildCGImage(char *str, CGNodeStatus stat);
    string buildSubImage(string sub_father, char *str, int *offset, CGNodeStatus stat);		// called by CGImage::buildCGImage to do recursive procedure
    
    void setSubState(string sub_ip, int sub_level, CGNodeStatus stat);	// set ONLINE/OFFLINE to sub_tree
    void setIpState(string sub_ip, CGNodeStatus stat, int level_down);	// set ONLINE/OFFLINE to nodes of IP level_down

    int indexCGNode(string cur_ip, int cur_level, string index, Set *set, int flag);	// index the node_set with same IP and different level in the sub_tree, recursively call indexSubNode
    int indexSubNode(string sub_ip, int sub_level, string index, Set *set, int flag);	// called by indexCGNode
    int indexIPNode(string index, Set *set);
    int indexChldNode(string cur_ip, int cur_level, Set *set);	// index the node_set of a node's children

public:
    /* function dealing with iamge */
    int getNodeState(string node_ip);
    string adjustImage(string sub_ip, CGNodeStatus sub_state, int *end_level, string *off_ip);
    int updateImage(string child, int s_level, char *str);
};


#endif
